/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package rukopisyimport.foxml;

import cz.mzk.kramerius.imports.FoxmlHelper;
import cz.mzk.kramerius.imports.Datastream;
import cz.mzk.kramerius.imports.Policy;
import cz.mzk.kramerius.imports.DatastreamFactory;
import cz.mzk.rehan.commons.DatastreamId;
import cz.mzk.rehan.commons.Namespaces;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.Node;
import org.dom4j.QName;
import rukopisyimport.sourceData.TeiDocument;
import rukopisyimport.sourceData.MarcDocument;

/**
 *
 * @author Martin Rehanek (rehan@mzk.cz)
 */
public abstract class AbstractPageBuilder {

    private static final Logger logger = Logger.getLogger(AbstractPageBuilder.class.getName());
    private final PageTitleResolver pageTitleResolver = new PageTitleResolver();

    public List<Page> createPages(File conversionDir, TeiDocument tei, MarcDocument marc) {
        List<Node> pageNodeList = tei.findPageNodeList();
        List<Page> pageList = new ArrayList<Page>(pageNodeList.size());
        int pageCounter = 0;
        for (Node surfaceNode : pageNodeList) {
            try {
                String uuid = FoxmlHelper.generateUuid();
                //String uuid = "test-page" + tei.findPageIndex(surfaceNode);
                Page page = createPage(tei, surfaceNode, uuid);
                pageList.add(page);
                createDatastreams(conversionDir, page, surfaceNode, marc, tei);
//            if (pageIndex == 12) {
//                break;//TODO: odstranit
//            }
                pageCounter++;
            } catch (Exception e) {
                logger.log(Level.SEVERE, e.getMessage());
            }
        }
        return pageList;
    }

    private Page createPage(TeiDocument tei, Node surfaceNode, String uuid) throws Exception {
        //String label = findLabel(tei, surfaceNode, pageCounter);
        String label = labelOrEmptyString(tei, surfaceNode);
        String id = findId(tei, surfaceNode);
        String urlSuffix = findUrlSuffix(tei, surfaceNode);
        return new Page(uuid, id, label, urlSuffix);
    }

    private String labelOrEmptyString(TeiDocument tei, Node surface) {
        String labelFromLabelEl = tei.pageLabel(surface);
        if (labelFromLabelEl == null) {
            return String.valueOf("");
        }
        return labelFromLabelEl;
    }

    private String findId(TeiDocument tei, Node surfaceNode) throws Exception {
        String id = tei.pageId(surfaceNode);
        if (id == null) {
            throw new Exception("Cannot find id");
        }
        return id;
    }

    private String findUrlSuffix(TeiDocument tei, Node surfaceNode) {
        return tei.pageUrlSuffix(surfaceNode);
    }

    private Integer findPageNumber(TeiDocument tei, Node surfaceNode) {
        return tei.pageNumberFromLabel(surfaceNode);
        //return tei.pageNumberFromSurfaceId(surfaceNode);
    }

    abstract void createDatastreams(File conversionDir, Page page, Node surfaceNode, MarcDocument marc, TeiDocument tei) throws Exception;

    Datastream createDcDatastream(Page page) throws Exception {
        Element rootElement = DocumentHelper.createElement(new QName("dc", Namespaces.oai_dc));
        rootElement.add(Namespaces.dc);
        Document doc = DocumentHelper.createDocument(rootElement);
        Element title = rootElement.addElement(new QName("title", Namespaces.dc));
        title.addText(page.getLabel());
        Element identifier = rootElement.addElement(new QName("identifier", Namespaces.dc));
        identifier.setText(page.getPid());
        Element type = rootElement.addElement(new QName("type", Namespaces.dc));
        type.addText("model:page");
        Element rights = rootElement.addElement(new QName("rights", Namespaces.dc));
        rights.addText("policy:" + Policy.PUBLIC.toString().toLowerCase());
        return DatastreamFactory.createInlineDatastream(doc, DatastreamId.DC);
    }

    Datastream createModsDatastream(Page page) {
        String pageLabel = page.getLabel();
        Element modsCollection = FoxmlHelper.createModsCollectionEl();
        Namespace modsNs = Namespaces.mods;
        Element mods = modsCollection.addElement(new QName("mods", modsNs));
        mods.addAttribute("version", "3.3");
        Element idUrn = mods.addElement(new QName("identifier", modsNs));
        idUrn.addAttribute("type", "urn");
        idUrn.addText(page.getUuid());

        Element idSici = mods.addElement(new QName("identifier", modsNs));
        idSici.addAttribute("type", "sici");

        Element typeOfResource = mods.addElement(new QName("typeOfResource", modsNs));
        typeOfResource.addText("text");
        Element part = mods.addElement(new QName("part", modsNs));
        part.addAttribute("type", pageTitleResolver.getPageType(pageLabel));
        //pageNumber
        Element detail = part.addElement(new QName("detail", modsNs));
        detail.addAttribute("type", "pageNumber");
        Element number = detail.addElement(new QName("number", modsNs));
        number.addText(pageLabel);
        //page index
        detail = part.addElement(new QName("detail", modsNs));
        detail.addAttribute("type", "pageIndex");
        number = detail.addElement(new QName("number", modsNs));
        number.addText(page.getLabel());
        Document doc = DocumentHelper.createDocument(modsCollection);
        return DatastreamFactory.createInlineDatastream(doc, DatastreamId.BIBLIO_MODS);
    }
}
